use anyhow::{anyhow, Error, Result};
use eastmoney::stock::stock_rpt_f10_basic_org_info::{
    RptF10BasicOrgInfo, RptF10BasicOrgInfoResultData,
};
use fudata::{db::Record, model::stock::Stock};
use reqwest::Client;

pub struct StockCraw {
    stock: Stock,
}
impl StockCraw {
    /// code: e.g. "000001", "300529", "600519", "688063", "837046"
    pub async fn update_basic_from_eastmoney(
        code: &str,
    ) -> Result<Option<Record>> {
        // 获取第一个字符
        let first_char = code.chars().next();

        // 根据第一个字符返回不同的字符串
        let secid = match first_char {
            Some('0') => format!("{code}.SZ"),
            Some('2') => format!("{code}.SZ"),
            Some('3') => format!("{code}.SZ"),
            Some('6') => format!("{code}.SH"),
            Some('8') => format!("{code}.BJ"),
            // 可以继续添加其他情况
            _ => format!("{code}"),
        };

        let jbgk = RptF10BasicOrgInfo::rpt_f10_basic_orginfo( &secid)
            .await
            .map_err(|err| anyhow!(err.to_string()))?;

        if let Some(dd) = jbgk.result.data.first() {
            let stock_craw: StockCraw = StockCraw::from(dd);
            let stock = stock_craw.stock;

            println!("\n\n stock= {:?}", stock);

            let updated = fudata::db::stock::upsert(code, stock).await?;

            Ok(updated)
        } else {
            Err(Error::msg("Nothing Done!"))
        }
    }
}

impl From<&RptF10BasicOrgInfoResultData> for StockCraw {
    fn from(v: &RptF10BasicOrgInfoResultData) -> Self {
        StockCraw {
            stock: Stock {
                fd_code: v.security_code.to_owned().unwrap_or_default().to_string(),
                code: v.security_code.to_owned().unwrap_or_default().to_string(),
                short_name: v
                    .security_name_abbr
                    .to_owned()
                    .unwrap_or_default()
                    .to_string(),
                full_name: match &v.former_name {
                    Some(v) => v.to_string(),
                    None => "".to_owned(),
                },
                ..Default::default()
            },
        }
    }
}

#[cfg(test)]
mod test {
    use fudata::db::Record;
    use surrealdb::sql::Thing;

    use crate::stock::stock_craw::StockCraw;

    #[tokio::test]
    async fn test_update_basic_from_eastmoney() {
        let _ = fudata::db::init().await.unwrap();

        let stock_codes = ["000001", "300529", "600519", "688063", "837046"];

        for code in stock_codes {
            let rs = StockCraw::update_basic_from_eastmoney( code).await;
            assert_eq!(rs.is_ok(), true);
            assert_eq!(
                rs.ok(),
                Some(Some(Record {
                    id: Thing {
                        tb: "stock".to_string(),
                        id: code.into()
                    }
                }))
            );
        }
    }
}
